package com.cskaoyan.javase.oop2.encapsulate._1extends._2conversion;

/**
 * 引用数据类型的类型转换
 *
 * 父类引用指向子类对象,实质上是"将一个指向子类对象的子类引用赋值给一个父类引用"
 * 这个过程就是引用数据类型的类型转换,就是引用数据类型的自动类型转换
 *
 * 接下来我们学习一下引用数据类型的类型转换的语法
 *
 * 1.引用数据类型的类型转换,能够发生了前提是什么?
 *      必须存在继承,必须发生在父类和子类之间
 *      这里实际上就体现了继承的一个优点:
 *      继承打破了Java引用数据类型的类型限制,自从有了继承,Java的引用数据类型出现了类型转换.
 *
 * 2.引用数据类型的类型转换,转换的是什么的类型?
 *      引用数据类型 = 引用 + 对象
 *      转换的是引用的数据类型
 *      对象的数据类型是不可以被转换的
 *
 * Java引用数据类型的类型转换,也分成以下两大类:
 *      1.引用数据类型的自动类型转换
 *      2.引用数据类型的强制类型转换
 *
 * 引用数据类型的自动类型转换
 *      1.发生的条件是什么?
 *          子类类型的引用 --> 父类类型的引用
 *          这个过程就是一个引用数据类型的自动类型转换
 *          引用数据类型的自动类型转换之所以能够自动发生,无需程序员写额外代码
 *          原因是子类"is-a"父类
 *          子类对象就可以直接当父类对象使用
 *          自动类型转换,自动完成,无需写其它额外代码.
 *
 *      2.(特殊的称呼,这是重要的概念)
 *          因为引用数据类型的自动类型转换,这个称呼太长了,而且引用数据类型的自动类型转换在开发中很常用
 *          所以就搞了一个简称,特殊的称呼
 *          在继承中,假设父类在上,子类在下,从继承的方向上来说,子类继承父类,是下面继承上面
 *          而引用数据类型的自动类型转换,从转换的方向上来说,是子类类型的引用 --> 父类类型的引用
 *          是从下面转换到上面
 *          所以它也被称之"向上转型"
 *
 * (浅谈)引用数据类型的强制类型转换(更详细的细节,我们后面再谈)
 *      1.发生的条件(通过编译的条件)是什么?
 *          父类类型的引用 --> 子类类型的引用
 *          这个过程中,相当于把父类引用指向的对象(父类引用指向的对象可能是父类对象,还可能是子类对象),当成一个子类类型去使用
 *          这在绝大多数时候是不可能的
 *          所以这里就不是自动转换了,而是强转
 *          强转需要特殊语法来完成,不会自动完成,强转的语法:
 *          强转后引用数据类型 对象名 =  (强转后引用数据类型)被强转的引用;
 *
 *      2.(重要,重点)能够正常执行,正常完成转换的条件是什么?
 *          如果乱进行强转,会导致程序抛出异常ClassCastException,终止执行,这个后果是比基本数据类型强转严重很多的
 *          所以引用数据类型的强制类型转换很危险,实际开发中要慎用
 *
 *
 *      3.(特殊的称呼,这是重要的概念)
 *          既然引用数据类型的自动类型转换被称之为"向上转型"
 *          那么引用数据类型的强制类型转换就称之为"向下转型"
 *
 * @since 17:27
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        Father fs = new Son();
        // 以上父类引用指向子类对象,可以变成以下三行代码
        Son s = new Son();
        Father f;
        // 直接把子类引用赋值给一个父类引用,没有报错
        f = s;

        System.out.println("--------------------");
        Father father = new Father();
        // 父 --> 子 是强转,必须写特殊语法,才能通过编译
        Son son = (Son) father;
    }

    public void test(){
        try {
            throw new CloneNotSupportedException();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }

}

class Father {

}

class Son extends Father {

}
